﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NativeWifi;
using WNADEP.DataCenter;
using WNADEP.DataCenter.NetworkDataSet;
using System.Threading;

namespace WNADEP.DataCenter
{
    class DataCenter
    {
        public volatile List<WIFISSID> globalSsids;
        private volatile bool _shouldStop;
        private WlanClient.WlanInterface _intf;

        public DataCenter(WlanClient.WlanInterface intf)
        {
            this._intf = intf;
        }

        public void UpdateGlobalSsids()
        {
            while (!_shouldStop)
            {
                this.globalSsids = ScanSSID(this._intf);
                Thread.Sleep(3000);
            }
        }
        public void RequestStop()
        {
            this._shouldStop = true;
        }

        public static List<WIFISSID> ScanSSID(WlanClient.WlanInterface _intf)
        {
            
            List<WIFISSID> ssids = new List<WIFISSID>();

            if (_intf == null) return ssids;

            Wlan.WlanAvailableNetwork[] networks = _intf.GetAvailableNetworkList(0);
            Wlan.WlanBssEntry[] bssList = _intf.GetNetworkBssList();


            if (networks == null || bssList == null) return ssids;

            Wlan.WlanAvailableNetwork foundNetwork = new Wlan.WlanAvailableNetwork();
            Wlan.WlanAssociationAttributes connectedAP = new Wlan.WlanAssociationAttributes();
            connectedAP = _intf.CurrentConnection.wlanAssociationAttributes;

            foreach (Wlan.WlanBssEntry bssEntry in bssList)
            {
                
                //WIFISSID targetSSID = new WIFISSID();
                //targetSSID.wlanInterface = _intf;

                string ssid = Encoding.UTF8.GetString(bssEntry.dot11Ssid.SSID, 0, (int)bssEntry.dot11Ssid.SSIDLength);
                
                //若ssid是属于可接入网络则加入到ssids中
                if( FindNetwork(ssid, networks, ref foundNetwork) )
                {
                    WIFISSID targetSSID = new WIFISSID( bssEntry.dot11Bssid );
                    //无线接口
                    targetSSID.wlanInterface = _intf;
                    //ssid
                    targetSSID.SSID = ssid;
                    //认证和加密算法
                    targetSSID.dot11DefaultAuthAlgorithm = foundNetwork.dot11DefaultAuthAlgorithm;
                    targetSSID.dot11DefaultCipherAlgorithm = foundNetwork.dot11DefaultCipherAlgorithm;
                    //链路质量
                    int num = ComputeRssi(bssEntry.linkQuality);
                    targetSSID.RSSI = (bssEntry.rssi > num) ? bssEntry.rssi : num;
                    if ( targetSSID.RSSI > 0 )
                        targetSSID.RSSI -= 256;

                    //信道类型
                    targetSSID.Channel = ConvertToChannel(bssEntry.chCenterFrequency);

                    //无线接入类型
                    targetSSID.BssType = ConvertToString(bssEntry.dot11BssType);

                    //信号质量
                    targetSSID.SignalQuality = foundNetwork.wlanSignalQuality;

                    //是否已连接
                    targetSSID.Connected = targetSSID.macAddress.CompareToPhysicalAddress(connectedAP.Dot11Bssid);

                    ssids.Add(targetSSID);
                                

                }
                
                //targetSSID.dot11DefaultAuthAlgorithm = bssEntry.dot11DefaultAuthAlgorithm;
                //targetSSID.dot11DefaultCipherAlgorithm = bssEntry.dot11DefaultCipherAlgorithm; 
              
                //targetSSID.wlanInterface = (int)bssEntry.linkQuality;
            }

            
            return ssids;
        }

        public static bool FindNetwork(string ssid, Wlan.WlanAvailableNetwork[] networks, ref Wlan.WlanAvailableNetwork foundNetwork)
        {
            if (networks != null)
            {
                foreach (Wlan.WlanAvailableNetwork network in networks)
                {
                    string str = Encoding.ASCII.GetString(network.dot11Ssid.SSID, 0, (int)network.dot11Ssid.SSIDLength);
                    if (!string.IsNullOrEmpty(str) && str.Equals(ssid))
                    {
                        foundNetwork = network;
                        return true;
                    }
                }
            }

            return false;
        }

        public static int ComputeRssi(uint linkQuality)
        {
            //
            // Make sure the link quality is within the range of [0..100]
            //
            if (linkQuality > 100)
                linkQuality = 100;
            //
            // Compute the RSSI based on the link quality. Link quality
            // is a percentage value between [0..100], where 0 equals -100dBm
            // and 100 equals -50dBm.
            //
            return (int)(.5 * linkQuality - 100);
        }

        public static uint ConvertToChannel(uint frequency)
        {
            uint retVal = 0;
            // 2.4 GHz
            if ((frequency > 2400000) && (frequency < 2484000))
                retVal = (frequency - 2407000) / 5000;

            if ((frequency >= 2484000) && (frequency <= 2495000))
                retVal = 14;

            // 5 GHz
            if ((frequency > 5000000) && (frequency < 5900000))
                retVal = (frequency - 5000000) / 5000;

            return retVal;
        }

        public static string ConvertToString(Wlan.Dot11BssType bssType)
        {
            string bssText;
            switch (bssType)
            {
                case Wlan.Dot11BssType.Infrastructure:
                    bssText = "Infrastructure";
                    break;
                case Wlan.Dot11BssType.Independent:
                    bssText = "Adhoc";
                    break;
                case Wlan.Dot11BssType.Any:
                    bssText = "AutoUnknown";
                    break;
                default:
                    bssText = "Unknown";
                    break;
            }

            return (bssText);
        }

        public static List<RemoteData> GenerateFakeRemoteData()
        {
            List<RemoteData> rlist = new List<RemoteData>();
            string[] PTL = { "tcp", "udp", "icmp", "icmp", "tcp" };
            string[] SIPL = { "192.168.1.1", "192.168.1.2", "192.168.1.3", "192.168.1.4", "192.168.1.5" };
            string[] SPortL = { "12322", "4445", "8210", "14463", "7580" };
            string[] DIPL = { "10.10.10.1", "10.10.10.2", "10.10.10.3", "10.10.10.4", "10.10.10.5", };
            string[] DPortL = { "22", "21", "80", "443", "8080" };
            string[] ProtocolL = { "ssh", "ftp", "http", "https", "http" };
            string[] FlagL = { "RSTR", "OTH", "REJ", "RSTO", "RSTOS0" };
            bool[] isEmergentL = { false, true, true, false, true };

            for (int i = 0; i < 5; i++)
            {
                RemoteData tmp = new RemoteData();
                tmp.SSID = "Fake SSID " + i.ToString();
                tmp.ProtocolType = PTL[i];
                tmp.SIP = SIPL[i];
                tmp.SPort = SPortL[i];
                tmp.DIP = DIPL[i];
                tmp.DPort = DPortL[i];
                tmp.Protocol = ProtocolL[i];
                tmp.Flag = FlagL[i];
                tmp.IsEmergent = isEmergentL[i];
                rlist.Add(tmp);
            }
            return rlist;
        }
    }
}
